package tump;

import java.util.*;

/**
 * @Author: sun
 * @Description:八叉树节点数据结构
 * @Data: create in 15:12 2019/1/27
 * @Modfied by:
 */
public class OctreeNode {
    /**
     * 一个立方体分为八个子结构，由下向上，按GEOHash编码顺序1到8
     * 分别是： |——|——|
     * 第二层： |  5 | 7  |
     *          |——|——|
     *          | 4  |  6 |
     *          |——|——|
     *          |——|——|
     * 第一层： |  1 | 3  |
     *          |——|——|
     *          | 0  |  2 |
     *          |——|——|
     * */

    /**
     * 节点的编号
     */
    private long id;
    /**节点表示的范围，使用两个12位的Base32字符串表示*/
    /*暂时不使用
    private String[] range = new String[2];*/
    /**
     * 节点的层数
     */
    private int level;
    /**
     * 节点数据计数count
     */
    private int count = 0;
    /**
     * 八叉树的节点最大容量
     */
    private final int MAXNODECOUNT = 4;
    /**
     * 使用arrList存储各个节点数据，8个list，数据LongID>>>(60-level)
     */
    private List<Long> arrList = new ArrayList<>();
    /**
     * 子节点map
     */
    private Map<Long, OctreeNode> octreeNodeMap = null;

    /**
     * @param level 节点的层级
     * @param id    节点的id
     *              初始化
     */
    public OctreeNode(/*String start ,String end,*/int level, long id) {
        /*
        this.range[0] = start;
        this.range[1] = end;
        */
        this.level = level;
        this.id = id;

    }

    public void add(Long longID) {
        count++;
        /*子节点为null，直接插入*/
        if(octreeNodeMap==null){
            arrList.add(longID);
        }else {
            /*直接向子节点插入*/
            Long childID = longID>>>(60-((this.level+1)*3));
            OctreeNode chileNode = octreeNodeMap.get(childID);
            chileNode.add(longID);
        }
        if(count==MAXNODECOUNT){
            split();
        }

    }

    public void split() {
        this.octreeNodeMap = new HashMap<>();
        for (Long i=0L;i<8;i++){
//            System.out.println(this.id*8+i);
            Long childID = this.id*8+i;
            int childLevel = this.level+1;
            this.octreeNodeMap.put(childID,new OctreeNode(childLevel,childID));
        }
        for (Object objectID:arrList){
            Long longID = (long)objectID;
            Long thisLevelLongID = longID>>>(60-(this.level)*3);
            Long nextLevelLongID = longID>>>(60-(this.level+1)*3);
            OctreeNode octreeNode = this.octreeNodeMap.get(nextLevelLongID);
            octreeNode.add(longID);
        }
        /*释放arrList*/
        this.arrList = null;


    }

    @Override
    public String toString() {
        return "OctreeNode{" +
                "id=" + id +
                ", level=" + level +
                ", count=" + count +
                ", octreeNodeMap=" + octreeNodeMap +
                '}';
    }
}
